/*
 * 
 * 
 * @author: Oren Zamir
 */
package org.valire.usermanagement.services;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.valire.usermanagement.beans.MethodAccessControl;
import org.valire.usermanagement.beans.Role;
import org.valire.util.persistency.GenericJpaDaoImpl;

/**
 * The Class UserDao.
 */
@SuppressWarnings("unchecked")
public class MethodAccessControlDao extends
		GenericJpaDaoImpl<MethodAccessControl, Integer> {

	/** The Constant logger. */
	private final static Logger logger = LoggerFactory.getLogger(MethodAccessControlDao.class);

	/**
	 * Instantiates a new user dao.
	 */
	public MethodAccessControlDao() {
		super(MethodAccessControlDao.class);
	}

	/**
	 * Gets the all available roles.
	 * 
	 * @return the all available roles
	 */
	public List<MethodAccessControl> getAllAvailableMethods() {
		List<MethodAccessControl> results = getJpaTemplate()
				.find("select mac from org.valire.usermanagement.beans.MethodAccessControl as mac ");
		if (results.size() == 0) {
			return null;
		}
		return results;
	}

	/**
	 * Gets the methods for roles.
	 *
	 * @param roles the roles
	 * @return the methods for roles
	 */
	public Set<MethodAccessControl> getMethodsForRoles(Set<Role> roles) {
		Set<MethodAccessControl> availableMethodsForRoles = new HashSet<MethodAccessControl>();
		List<MethodAccessControl> allAvailableMethods = this.getAllAvailableMethods();
		
		if (allAvailableMethods == null ) return null;
		
		Iterator<MethodAccessControl> it = allAvailableMethods.iterator();
		while (it.hasNext()) {
			MethodAccessControl methodAccessControl = (MethodAccessControl) it.next();
			
			
			Iterator<Role> role_it = roles.iterator();
			while (role_it.hasNext()) {
				Role role = (Role) role_it.next();
				if (logger.isDebugEnabled())
					logger.debug("looking for method '{}' with role '{}' : ",methodAccessControl.getMethodName(),role.getRoleName());
				
				
				Set<Role> method_roles = methodAccessControl.getRoles();
				Iterator<Role> m_it = method_roles.iterator();
				while (m_it.hasNext()) {
					Role role2 = (Role) m_it.next();
					if (logger.isDebugEnabled())
						logger.debug("method '{}' has role '{}' : ",methodAccessControl.getMethodName(),role2.getRoleName());
					
					if (role.equals(role2)){
						availableMethodsForRoles.add(methodAccessControl);
						break;
					}
				}
			}
		}

		return availableMethodsForRoles;
	}

	/**
	 * Can user access method.
	 * 
	 * @param user
	 *            the user
	 * @param method
	 *            the method
	 * @return true, if successful
	 */
	public boolean canRoleAccessMethod(Role role, String method) {

		Set<Role> roles = new HashSet<Role>(1);
		roles.add(role);
		Set<MethodAccessControl> methods = this.getMethodsForRoles(roles);
		
		if (methods == null) return false;
		
		Iterator<MethodAccessControl> iterator = methods.iterator();
		while (iterator.hasNext()) {
			MethodAccessControl methodAccessControl = (MethodAccessControl) iterator
					.next();

			// debug
			if (logger.isDebugEnabled()){
				logger.debug("role '{}' has access to method '{}' ",role.getRoleName() ,methodAccessControl.getMethodName());
				logger.debug("comparing : '{}' , '{}'",method,methodAccessControl.getMethodName());
			}
			
			try {
				if (method.matches(methodAccessControl.getMethodName())){
					if (logger.isDebugEnabled())
						logger.debug("'{}' does equal '{}'",method,methodAccessControl.getMethodName());
					return true;
				}				
			} catch (java.util.regex.PatternSyntaxException e) {
				if (logger.isWarnEnabled())
					logger.warn("Exception caught for method matching : {}",e.getMessage());
			}
			
			// debug
			if (logger.isDebugEnabled())
				logger.debug("'{}' does NOT equal '{}'",method,methodAccessControl.getMethodName());
			
		}

		return false;
	}

}
